package hw01;

import java.sql.Timestamp;

/**
 * <p>The interface is used to invoke a set of functions, from standard 
 * input by listing the function name followed by its arguments, one per line.</p>
 * 
 * <p>For example, the {@link #connect(String, String)} function takes two arguments 
 * and me be invoked as follows (using example values for the arguments): 
 * <pre>
 * {@code
 * connect
 * bigmoose
 * xyzzy
 * }
 * </pre>
 * </p>
 * 
 * <p>String arguments will be listed verbatim, with no quotes or other 
 * demarcation.  It is assumed that function arguments do not contain 
 * any newline characters.  Integers will be listed in conventional format
 * (e.g., 123, 74).  It is assumed that all numbers are in the range 
 * [0, 10^5].  Date-time values are in UTC, with the format 
 * YYYY-MM-DD HH:MM:SS, along the lines of ISO 8601 standard.
 * For example, 2011-09-23 09:04:02 denotes two seconds past 9:04 a.m. 
 * UTC on the 23rd of September, 2011 (the Autumnal Equinox).  Unless 
 * otherwise specified, it is assumed that all string-valued attributes 
 * contain at most 100 characters.  An exception is the {@code comments} 
 * attribute of {@code Facilities}, which may contain up to 100,000 characters.  
 * The program will ignore lines with # (pound sign) as the first character.  
 * It also ignores blank lines, but blank lines separating function invocations 
 * are <em>not</em> required.  The program will read and process the functions 
 * in the order in which they appear in and terminate gracefully (e.g., by 
 * closing open database connections) when the end of input is reached.  There 
 * is no error-handling features for invalid input.<p>
 * 
 * @param I Identifier type for Rooms
 * @param F Identifier type for Facilities
 * @param C Identifier type for Reservations
 * @author Joshua Belanger
 * @version 1.0
 */
public abstract class Questions<I, F, C> {
	
	/**
	 * <p>When the work (both internal processing and output to user)
	 * for each function is done, the application writes 
	 * {@code FUNCTION_TERMINATION} (to standard output).</p>
	 */
	public static final String FUNCTION_TERMINATION = "-----\n";
	
	/**
	 * <p>{@code SEPARATOR} is assumed not to be a substring of any valid 
	 * string input to this application.</p>
	 */
	public static final String SEPARATOR = " : ";
    
    /**
     * <p>A <em>session</em> begins when the application program is invoked and ends 
     * when the end of input is reached on the standard input.  This function 
     * will be the first one invoked in any session, and it will be invoked exactly 
     * once per session.  In response, the application performs all necessary 
     * initialization and connects to the database server as user {@code u} with 
     * password {@code p}.  Strictly speaking, the program need not perform any 
     * of these actions, since its observable behavior for this function does not 
     * depend on them.</p>
     * 
     * @param u user to connect to database as
     * @param p password of user to connect to database as
     */
    public abstract void connect(String u, String p) throws Exception;
    
    /**
     * <p>This function results in the creation of the database tables described on 
     * page 2 of the homework, if they do not already exist in the database.  
     * This function will be called before any functions below.</p>
     */
    public abstract void createTables() throws Exception;
    
    /**
     * <p>This function results in the removal of the database tables created by 
     * {@link #createTables()}, if they are present in the database.  After 
     * {@link #destroyTables()}, the database should be in its initial pristine 
     * state (with no user tables).  It is assumed that after this function is 
     * called, a call to {@link #createTables()} will precede a call to any of 
     * the functions described below.</p>
     */
    public abstract void destroyTables() throws Exception;
    
    /**
     * <p>When this function is invoked, the application adds a new row 
     * (i, b, f, r, d) to the {@code Rooms} table.</p>
     * 
     * @param b Building attribute of rooms row
     * @param f Floor attribute of rooms row
     * @param r Room number attribute of rooms row
     * @param d Directions attribute of rooms row
     * @return Identifier i for row added
     */
    public abstract I addRoom(final String b, final int f, final int r, final String d) throws Exception;
    
    /**
     * <p>This function searches for rooms for which {@code s} occurs as a substring 
     * of either building name or directions (or both).  This search, and <em>all 
     * searches on string-valued attributes</em>, is case-insensitive unless specified 
     * otherwise.  The matching room records are printed one per line.  Each line 
     * contains the room's identifier (see {@link #addRoom(String, int, int, String)}), 
     * building name, and room number, separated using {@link #SEPARATOR}.  The output 
     * is sorted in ascending lexicographic order of building name (case insensitive) 
     * and ascending order of room numbers (secondary sort order).  Output lines here 
     * and elsewhere are terminated by a single newline character.</p>
     * 
     * @param s Occurs as a substring of either building name or directions (or both) 
     * of the search results.
     * @see #addRoom(String, int, int, String)
     * @see #SEPARATOR
     */
    public abstract void findRoom(String s) throws Exception;
    
    /**
     * <p>This function should print descriptive information about the room identified 
     * by the given identifier <em>i (exact, case-sensitive</em> string match).  If 
     * there is no room with identifier <em>i</em>, no output should produced and 
     * this condition is not an error.  If the room identified by <em>i</em> exists, 
     * the following information should be printed on a single line (in this order): 
     * building name, room number, floor, number of chairs, and number of screens.</p>
     * 
     * <p>For this and other functions, attribute values and other items printed on an 
     * output line are separated using the {@link #SEPARATOR} string.  Strings 
     * are printed literally (with no quotes, padding, or other artifacts).  Integers 
     * and dates are printed in the format used for the input.</p>
     * 
     * @param i Room identifier
     * @see #addRoom(String, int, int, String)
     * @see #SEPARATOR
     */
    public abstract void describeRoom(I i) throws Exception;
    
    /**
     * <p>When this function is invoked, the application adds a row 
     * <em>(f, b, r, c, s)</em> to the <em>Facilities</em>  table, where 
     * <em>s, e, b, r</em> and <em>s</em> denote, respectively, the building name, 
     * room number, number of chairs, and number of screens, and where <em>f</em> 
     * is an identifier similar to that used in {@link #addRoom(String, int, int, String)}.  
     * The output of this function is identifier <em>f</em>.</p>
     * 
     * @param b Building attribute of facility row
     * @param r Room attribute of facility row
     * @param c Chairs attribute of facility row
     * @param s Screens attribute of facility row
     * @param d Comments attribute of facility row
     * @return Identifier f of facility added
     */
    public abstract F addFacilities(String b, int r, int c, int s, String d) throws Exception;
    
    /**
     * <p>When this function is invoked, the application adds a row <em>(c, s, e, b
     * , r, n)</em> to the <em>Facilities</em> table, where <em>b, r, c,</em> and 
     * <em>n</em> denote, respectively, the start and end times of the reservation, 
     * the building name, the room number, and the name of the person making the 
     * reservation.  The identifier <em>c</em> is a reservation confirmation number 
     * (identifier) that is also the output of this function.</p>
     * 
     * @param s Start time of reservation row
     * @param e End time of reservation row
     * @param b Building name of reservation row
     * @param r Room number of reservation row
     * @param n Name of person making the reservation
     * @return Identifier c of reservation added
     */
    public abstract C addReservation(Timestamp s, Timestamp e, String b, int r, String n) throws Exception;
    
    /**
     * <p>This function prints descriptive information about the room reservation 
     * identified by the given identifier (confirmation number) c (<em>exact, case-
     * sensitive</em> string match).  If there is no reservation matching identifier 
     * c, no output is produced and this condition is not an error.  If the reservation 
     * by c exists, the following information should be printed on a single line (in 
     * this order): building name, room number, start time, end time, and name of 
     * reservation holder.</p>
     * 
     * @param c confirmation number
     */
    public abstract void describeReservation(C c) throws Exception;
    
    /**
     * <p>This function is similar to {@link #addReservation(Timestamp, Timestamp, String, int, String)}, 
     * differing only in how the begin and end times of the reservation are specified.  Instead of 
     * these times being specified explicitly, they are specified using a <em>time-pattern p</em> and 
     * <em>time-length l</em> as described below.  The other arguments (<em>b, r, and n</em>) are 
     * treated as in {@link #addReservation(Timestamp, Timestamp, String, int, String)}.  Recall 
     * that all times are in UTC.</p>
     * 
     * <p>The begin times are based on interpreting the time-pattern <em>p</em> as a <em>crontab</em> 
     * expression.  The expression <em>p</em> consisits of five fields (minute, hour, day of month, 
     * month, and day of week) separated by whitespace.  The following excerpt (slightly modified) 
     * from the crontab manual describes the semantics.</p>
     * 
     * <p>[A timestamp matches p] when the minute, hour, and month of year fields match the current time, 
     * and when at least one of the two day fields (day of month, or day of week) match the current time.  
     * The time and date fields are:
     * 
     * <table>
     * <tr><th>field</th><th>allowed values</th></tr>
     * <tr><td>minute</td><td>0-59</td></tr>
     * <tr><td>hour</td><td>0-23</td></tr>
     * <tr><td>day of month</td><td>1-31</td></tr>
     * <tr><td>month</td><td>1-12 or names</td></tr>
     * <tr><td>day of week</td><td>0-7 (0 and 7 mean Sun.)</td></tr>
     * <tr><td>[year]</td><td>[integer year of common era]</td></tr>
     * </table>
     * </p>
     * 
     * <p>A field may be an asterisk (*), which always stands for "first-last."</p>
     * 
     * <p>Ranges of numbers are allowed.  Ranges are two numbers separated with a hyphen.  The specified 
     * range is inclusive.  For example, 8-11 for an "hours" entry specifies [a reservation] at hours 
     * 8, 9, 10 and 11.  [Similarly, 2009-2011 specifies a reservation for years 2009, 2010 and 2011 C.E.  
     * We will assume a temporal granularity of one minute.  Thus the time-pattern * * 1 1 * 2009 
     * specifies the time points marking each minute of each hour of January 1st, 2009 (a total of 60x60 
     * points in time).</p>
     * 
     * <p>List are allowed.  A list is a set of numbers (or ranges) separated by commas.  
     * Examples: "1,2,5,9"; "0-4,8-12."</p>
     * 
     * <p>Step values can be used in conjunction with ranges.  Following a range with "/<number>" 
     * specifies skips of the number's value through the range.  For example, "0-23/2" can be 
     * used in the hours field to specify command execution every other hour (the alternative in 
     * the V7 standard is "0,2,4,6,8,10,12,14,16,18,20,22).  Steps are also permitted after an 
     * asterisk, so if you want to say "every two hours," just use "* /2".</p>
     * 
     * <p>Names can also be used for the "month" and "day of week" fields.  Use the first three 
     * letters of the particular day or month (case doesn't matter).  Ranges or lists of names 
     * are not allowed.</p>
     * 
     * <p>A single invocation of {@link #makeReservations(String, int, String, int, String)} 
     * creates, in general, several entries in the Reservations table.  We will refer to this 
     * group of reservations as a <em>reservation group</em>. The time-length argument specifies 
     * following invocation results in 24 reservations for January 15th, 2011 for the first 10 
     * minutes of each hour of that day:
     * <code>makeReservation(0 * 15 * 2011, 10, Neville, 210, Alice)</code>
     * </p>
     * 
     * <p><b>Time-limit Assumption.</b>  You may ignore reservations beyond 2012-12-31 23:59:59.  
     * For patterns that specify reservations both before and after this timestamp, only the 
     * reservations after the date may be ignored; the earlier ones must be managed properly.  
     * This assumption may simplify your implementation of invocations such as the following:
     * <code>makeReservation(0 * 15 1 * *, 10, Neville, 210, Alice)</code></p>
     * 
     * @param p Cron pattern
     * @param l Reservation length (in minutes)
     * @param b Building name
     * @param r Room number
     * @param n Name of person
     * @see #addReservation(Timestamp, Timestamp, String, int, String)
     */
    public abstract void makeReservations(String p, int l, String b, int r, String n) throws Exception;
    
    /**
     * <p>This function finds reservations for room number <em>r</em> in building 
     * <em>b</em> such that there is at least one instant of time that matches the 
     * time-pattern <em>p</em> and lies between the begin and end of times of the 
     * reservation (including the end-points).  The interpretation of <em>p</em> 
     * is identical to that of {@link #makeReservations(String, int, String, int, String)} 
     * The output consists of the confirmation numbers of the matching reservations, 
     * one per line.</p>
     * 
     * @param p Cron pattern
     * @param b Building name
     * @param r Room number
     * @see #makeReservations(String, int, String, int, String)
     */
    public abstract void matchReservation(String p, String b, int r) throws Exception;
    
    /**
     * <p>This function finds rooms that are unreserved at all times matching the 
     * time-pattern <em>p</em> and <em>l</em>, which are interpreted as in 
     * {@link #makeReservations(String, int, String, int, String)}.  In 
     * addition, the matching rooms are required to have at least <em>c</em> 
     * chairs and <em>s</em> screens.  The output consists of the building 
     * and room-number for each matching room, one per line.  A room is 
     * considered unreserved at a time matching <em>p</em> only if it is 
     * unreserved for the entire length of each interval specified by <em>p</em> 
     * and <em>l</em>.  If the facilities (number of chairs and screens) of a 
     * room are known, the room does not match.</p>
     * 
     * @param p Cron pattern
     * @param l Reservation length (in minutes)
     * @param c Number of chairs
     * @param s Number of screens
     */
    public abstract void getFreeRoom(String p, int l, int c, int s) throws Exception;
    
}
